#####################
# run.py - 5 march 2012 - Hessel van der Molen
# Runs & tests 2 defined agents in the domination game.
#####
# USAGE:
# 
# shell> python run.py [elements]
# [elements] is:

# -r <redagent.py>              (pythonfile     default: defaultAgent)
# -b <blueagent.py>             (pythonfile     default: defaultAgent)
# -rb <{red,blue}agent.py>      (pythonfile     default: defaultAgent) -> both players are the same agent
# -qr <qtable_red.txt>          (picklefile     default: None)
# -qb <qtable_blue.txt>         (picklefile     default: None)
# -qrb <qtable_{red,blue}.txt>  (picklefile     default: None) -> both agents use the exact same qtable (12 tanks write to 1 file!)
# -n <numberOfGamesToPlay>      (integer        default: 1)
# -d <Show/Render_Game>         (true/false     default: true)
# -s <stepPerGame>              (integer        default: 600)
# -t <ThinkTimeAgent>           (float(seconds) default: 0.1 seconds)
# -e <AgentToEvaluatue>         (red/blue       default: red)

# enable to run code in map-structure:
import os, sys, time, pickle
path, filename = os.path.split("../Domination-Game/domination")
sys.path.append(path)
defaultAgent = '../Domination-Game/domination/agent.py'

#code to run game
from domination import core, run

#default values
redAgent = defaultAgent
blueAgent = defaultAgent
render = 'true'
iterations = 1
max_steps = 600
think_time = 0.1
evaluate = 'red'
qtableRedFile = None
qtableBlueFile = None

arguments = len(sys.argv) - 1
if (arguments%2 == 1):
    print "ERROR not an even number of arguments given"
    print str(len(sys.argv)) + " " + str(sys.argv)
else:
    # set commands
    for i in range(arguments/2):
        cmd = sys.argv[i*2+1]
        val = sys.argv[i*2+2]
        
        if (cmd == '-rb'):          #agents are equal
            redAgent = val
            blueAgent = val
        elif (cmd == '-r'):         #red agend
            redAgent = val
        elif (cmd == '-b'):         #blue agent
            blueAgent = val
        elif (cmd == '-n'):         #number of iterations
            iterations = int(val)
        elif (cmd == '-d'):         # display/render?        
            render = val
        elif (cmd == '-s'):         # number of steps per game
            max_steps = int(val)
        elif (cmd == '-t'):         # think time of agent
            think_time = float(val)
        elif (cmd == '-qrb'):       # Q-table to use in both agents (they share it: 12 updates per run in game!)
            qtableRedFile = val
            qtableBlueFile = val           
        elif (cmd == '-qr'):        # Q-table to use for red agent
            qtableRedFile = val
        elif (cmd == '-qb'):        # Q-table to use for blue agent
            qtableBlueFile = val  
        elif (cmd == '-e'):         # agent to evaluate
            evaluate = val            
        else:                       # not recognised
            print "Incorrect Command: " + cmd
    
    # Define settings
    settings = core.Settings(max_steps=max_steps, think_time=think_time)

    # list for keeping track of all scores
    score = []
    steps = []
    states = []

    # Load Q-table(s)
    qtableRed = None
    qtableBlue = None

    # load qtable red (if existing)
    if (qtableRedFile is not None):
        # open file
        FILE = open(qtableRedFile, 'rb')
        qtableRed = pickle.loads(FILE.read())
        FILE.close()    
    
    # load qtable blue (if existing)
    if (qtableBlueFile is not None):
        if (qtableRedFile == qtableBlueFile):
            # share q-table
            qtableBlue = qtableRed
        else:
            # open file
            FILE = open(qtableBlueFile, 'rb')
            qtableBlue = pickle.loads(FILE.read())
            FILE.close()    
    
    #create blob-reference for game
    red_init = {'blob': qtableRed} if qtableRed is not None else {}
    blue_init = {'blob': qtableBlue} if qtableBlue is not None else {}

    # Run game(s)
    start = time.time()
    for a in range(iterations):
        
        #run game
        print('> Running Game #' + str(a+1))
        if (render == 'true'):
            game = core.Game(redAgent, blueAgent, red_init=red_init, blue_init=blue_init, record=True, rendered=True, settings=settings)
        else: 
            game = core.Game(redAgent, blueAgent, red_init=red_init, blue_init=blue_init, record=False, rendered=False, settings=settings)
        game.run()
            
        #evaluate score & swap agents
        #swapping is done to make sure there is no advantage in team-color
        if (evaluate == 'red'): 
            score.append(game.score_red)
            evaluate = 'blue'
            # append length of q-table
            if (qtableRed is not None):
                states.append(len(qtableRed))
        else:
            score.append(game.score_blue)
            evaluate = 'red'
            # append length of q-table
            if (qtableBlue is not None):
                states.append(len(qtableBlue))
            
        #store q-table
        if (qtableRedFile is not None):
            file = open(qtableRedFile, 'w')
            pickle.dump(qtableRed,file)
            file.close()
            
        if ((qtableBlueFile is not None) and (qtableBlueFile is not qtableRedFile)):
            file = open(qtableBlueFile, 'w')
            pickle.dump(qtableBlue,file)
            file.close()
                
        #number of game-steps, the game last
        steps.append(game.step)
        
        # switch agents & qtables (blue = red & red = blue)
        redAgent, blueAgent = blueAgent, redAgent
        red_init, blue_init = blue_init, red_init
        qtableRed, qtableBlue = qtableBlue, qtableRed
        qtableRedFile, qtableBlueFile = qtableBlueFile, qtableRedFile
        
    
    #calculate duration
    end = time.time()
    duration = str(int(end-start))
    print('> The duration was: '+duration+' seconds')

    # if multiple games are played store score results
    if (len(score) > 1):
        import datetime
        now = datetime.datetime.now()
        filename = "results/"
        filename += str(now.year)
        filename += "_" + str(now.month)
        filename += "_" + str(now.day)
        filename += "_" + str(now.hour)
        filename += "_" + str(now.minute) 
        if (evaluate == 'blue'): #evaluate switches, but game not! (check above loop)
            filename += "_" + game.red.fullname() + ".txt"
        else:
            filename += "_" + game.blue.fullname() + ".txt"
        file = open(filename, "w")
        file.write(str(score))
        file.write("\n")
        file.write(str(steps))
        file.write("\n")
        file.write(str(states))
        file.close()
